package cn.maidouya.user.service.impl;

import cn.maidouya.basic.constants.UserConstants;
import cn.maidouya.basic.exception.BusinessExcepiton;
import cn.maidouya.basic.util.AjaxResult;
import cn.maidouya.basic.util.HttpClientUtils;
import cn.maidouya.basic.util.MD5Utils;
import cn.maidouya.basic.util.StrUtils;
import cn.maidouya.user.domain.Logininfo;
import cn.maidouya.user.domain.User;
import cn.maidouya.user.domain.WxUser;
import cn.maidouya.user.dto.LoginDto;
import cn.maidouya.user.dto.UserDto;
import cn.maidouya.user.mapper.LogininfoMapper;
import cn.maidouya.user.mapper.UserMapper;
import cn.maidouya.user.mapper.WxUserMapper;
import cn.maidouya.user.service.ILoginService;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements ILoginService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private WxUserMapper wxUserMapper;
    @Autowired
    private UserMapper userMapper;

    /**
     *  手机号码登录
     * @param loginDto
     * @return
     */
    @Override
    public Map<String, Object> accountLogin(LoginDto loginDto) {
        // 较空
    if (StringUtils.isEmpty(loginDto.getUsername()) || StringUtils.isEmpty(loginDto.getUsername()) ||
         StringUtils.isEmpty(loginDto.getPassword()) ||  StringUtils.isEmpty(loginDto.getType()) ){
        throw new BusinessExcepiton("请完整输入登录信息");
    }
        // 校验账号
        Logininfo info =logininfoMapper.loadByUser(loginDto);
        if (info == null){
            throw new BusinessExcepiton("用户不存在，请注册！！");
        }
        // 校验密码
        String salt = info.getSalt();// 获取数据库中盐值
        // 用户使用明文   后台采用盐值后与数据库中信息做判断
        String md5 = MD5Utils.encrypByMd5(loginDto.getPassword() + salt);
        if (!md5.equalsIgnoreCase(info.getPassword())){
         throw new BusinessExcepiton("密码错误，请重新输入！！");
        }
        // 校验状态
        if (info.getDisable() != 1){
            throw new BusinessExcepiton("用户被禁用，请联系客服！！");
        }
        // 登录成功

        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token,info,30, TimeUnit.MINUTES);
        Map<String, Object> map = new HashMap<>();
        map.put("token",token);
        info.setSalt(null);
        info.setPassword(null);
        map.put("logininfo",info);
        // 登录成功返回对象给到管理员登录
        return map;
    }

    /**
     *   微信登录
     * @param code 微信授权码
     * @return
     */
    @Override
    public AjaxResult wechatLogin(String code) {
        // 第一步  拿到token用户登录信息
        String getTokenUrl = UserConstants.GET_TOKEN_URL
                .replace("APPID", UserConstants.APPID)
                .replace("SECRET", UserConstants.SECRET)
                .replace("CODE", code);
        String tokenStr = HttpClientUtils.httpGet(getTokenUrl);
        if (StringUtils.isEmpty(tokenStr)){
            throw new BusinessExcepiton("获取用户不存在");
        }
        // token对象转换为json对象
        JSONObject tokenObj = JSONObject.parseObject(tokenStr);
        // 每个属性转为为String类型属性值
        String accessToken = tokenObj.getString("access_token");
        String openId = tokenObj.getString("openid");

        // 第二步 查询wx_user表中是否 存在微信用户
        WxUser wxUser = wxUserMapper.loadByOpenId(openId);
        // 微信openId和微信用户仔仔wx_user表中存在   可以免密登录
        if (wxUser != null && accessToken != null){
            // 微信用户存在免密登录，wx_user关联表user_id是否存在
           Logininfo info = logininfoMapper.loadByUserId(wxUser.getUser_id());
           // 生成token键
            String token = UUID.randomUUID().toString();
            // 存储Redis数据库
            redisTemplate.opsForValue().set(token,info,30,TimeUnit.MINUTES);
            // token和logininfo 给前台
            Map<String, Object> map = new HashMap<>();
            map.put("token",token);
            info.setSalt(null);
            info.setPassword(null);
            map.put("logininfo",info);
            // 通过AjaxResult绑定数据给到前台
            return AjaxResult.getResult().setResultObj(map);
        } else {
            // 在wx_user表没有微信用户,重新拼接数据回到前端绑定信息callback.html钩子函数   注意：拼接问题
           String resultUrlParam = "accessToken="+accessToken+"&openId="+openId;
            // accessToken43_TD0Jck7ATE1w_E5CvCLkkaTl3mw9Iwvyu9Gv5x2N_MOu4d8Y6Bz_3T9uM89yQDAUBAZbOpKRy4EVaO1bhR6sJaOngeAflPVeArITZRGh2Mk&openIdoa9wA0wtq7cYn_geAQaKDxxHHZ_Y
            return AjaxResult.getResult().setSuccess(false).setResultObj(resultUrlParam);
        }
    }

    /**
     *   绑定微信用户
     * @param param
     * @return
     */
    @Override
    public Map<String, Object> binderWechat(Map<String, String> param) {
        String accessToken = param.get("accessToken");
        String openId = param.get("openId");
        String phone = param.get("phone");
        String verifyCode = param.get("verifyCode");
        // 第一步  较空未填写信息提示用户完善信息绑定
        if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(verifyCode) || StringUtils.isEmpty(accessToken) || StringUtils.isEmpty(openId)){
            throw new BusinessExcepiton("请完善登录信息！！");
        }
        // 校验验证码  这个获取的Redis验证码
        Object codeObj = redisTemplate.opsForValue().get(UserConstants.BINDER_CODE_PREFIX + phone);
        if (codeObj == null){
            throw new BusinessExcepiton("验证码已失效，请重新获取！！");
        }
        String code = ((String)codeObj).split(":")[0];
        // 用户输入验证码和Redis中的验证码是否一致
        if(!code.equalsIgnoreCase(verifyCode)){
            throw new BusinessExcepiton("输入验证码不正确，请重新输入");
        }
        // 第二步 校验用户是否存在
        User user = userMapper.loadByPhone(phone);
        Logininfo info = null;
        if(user == null){
            // 创建用户到user表
            user = initUserByPhone(phone);
            // user表用户拷贝到logininfo表
            info = user2Logininfo(user);
            logininfoMapper.save(info);
            user.setLogininfo_id(info.getId());
            userMapper.save(user);
        }else {
            // 注册过用户信息，查询出来
            info = logininfoMapper.loadById(user.getLogininfo_id());
        }
        // 第三步 通过token查询用户信息  获取要绑定用户信息
        String getTokenUrl = UserConstants.GET_WXUSER_URL
                .replace("ACCESS_TOKEN", accessToken)
                .replace("OPENID", openId);
        //System.err.println("微信携带了啥： " +getTokenUrl);
        String wxUseTtoken = HttpClientUtils.httpGet(getTokenUrl);
        //System.err.println("是什么数据： " +wxUseTtoken);

        // 第四步 生成微信用户并绑定微信用户
            // 从绑定用户平台到用户平台   wx_user拷贝到t_user表
            WxUser wxUser = user2Wxuser(wxUseTtoken,user);
            wxUserMapper.save(wxUser);
      // 第五步  可以免密登录
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token,info,30,TimeUnit.MINUTES);
        Map<String, Object> map = new HashMap<>();
        map.put("token",token);
        info.setSalt(null);
        info.setPassword(null);
        map.put("logininfo",info);
        return map;
    }


    private WxUser user2Wxuser(String wxUseTtoken, User user) {
        // wxUseTtoken转化为json对象   user给wx_user的关联id
        JSONObject jsonObject = JSONObject.parseObject(wxUseTtoken);
        WxUser wxUser = new WxUser();
        wxUser.setUser_id(user.getId());
        wxUser.setOpenid(jsonObject.getString("openid"));
        wxUser.setNickname(jsonObject.getString("nickname"));
        wxUser.setSex(jsonObject.getInteger("sex"));
        wxUser.setAddress(null);
        wxUser.setHeadimgurl(jsonObject.getString("headimgurl"));
        wxUser.setUnionid(jsonObject.getString("unionid"));
        return wxUser;
    }

    /**
     *    微信绑定用户修改到logininfo表
     * @param user
     * @return
     */
    private Logininfo user2Logininfo(User user) {
        Logininfo info = new Logininfo();
        BeanUtils.copyProperties(user,info);
        info.setType(1);// 用户是1
        return info;
    }

    /**
     *   微信绑定用户信息修改到user表
     * @param phone
     * @return
     */
    private User initUserByPhone(String phone) {
        User user = new User();
        user.setUsername(phone);
        user.setPhone(phone);
        String randomString = StrUtils.getComplexRandomString(32);
        user.setSalt(randomString);
        // 密码是随机生成6位
        String md5 = MD5Utils.encrypByMd5(StrUtils.getComplexRandomString(6) + randomString);
        user.setPassword(md5);
        return user;
    }
}
